package com.wjk.kylin.mall.auth.config;

import com.wjk.kylin.mall.auth.security.core.userdetails.user.AdminUserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AdminUserDetailsServiceImpl adminUserDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http    // 使用jwt,则无需使用原本的session管理
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .and()// actuator中的所有健康检查端点都放行,经测试,此处包含了上述几处oauth端点,直接放行
                .authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .and()
                // 对于登录login/admin 验证码login/captcha 允许匿名访问
//                .authorizeRequests().antMatchers("/login/**").anonymous()
//                .and()// 此处不加项目的context-path
                .authorizeRequests().antMatchers("/rsa/publicKey","/oauth/logout").permitAll()
                .anyRequest().authenticated()// 除上面外的所有请求全部需要鉴权认证
                .and()
                .csrf().disable();
        /**
         * anonymous 仅允许匿名用户访问,如果登录了访问 反而没权限(亲测)
         * permitAll 登录能访问,不登录也能访问,一般用于静态资源js等
         */
    }

    /**
     * 如果不配置SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(daoAuthenticationProvider());

//        auth.authenticationProvider(wechatAuthenticationProvider()).
//                authenticationProvider(daoAuthenticationProvider()).
//                authenticationProvider(smsCodeAuthenticationProvider());
    }

//    /**
//     * 手机验证码认证授权提供者
//     *
//     * @return
//     */
//    @Bean
//    public SmsCodeAuthenticationProvider smsCodeAuthenticationProvider() {
//        SmsCodeAuthenticationProvider provider = new SmsCodeAuthenticationProvider();
//        provider.setUserDetailsService(memberUserDetailsService);
//        provider.setRedisTemplate(redisTemplate);
//        return provider;
//    }

//    /**
//     * 微信认证授权提供者
//     *
//     * @return
//     */
//    @Bean
//    public WechatAuthenticationProvider wechatAuthenticationProvider() {
//        WechatAuthenticationProvider provider = new WechatAuthenticationProvider();
//        provider.setUserDetailsService(memberUserDetailsService);
//        provider.setWxMaService(wxMaService);
//        provider.setMemberFeignClient(memberFeignClient);
//        return provider;
//    }


    /**
     * 用户名密码认证授权提供者
     *
     * @return
     */
    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(adminUserDetailsService);
        provider.setPasswordEncoder(passwordEncoder());
        provider.setHideUserNotFoundExceptions(false); // 是否隐藏用户不存在异常，默认:true-隐藏；false-抛出异常；
        return provider;
    }


    /**
     * 密码编码器
     * <p>
     * 委托方式，根据密码的前缀选择对应的encoder，例如：{bcypt}前缀->标识BCYPT算法加密；{noop}->标识不使用任何加密即明文的方式
     * 密码判读 DaoAuthenticationProvider#additionalAuthenticationChecks
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}
